# -*- mode: python -*-
###
#
# (c) 2000-2007 Wijnand Modderman <wijnand at tehmaze dot com>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
#   * Redistributions of source code must retain the above copyright notice,
#     this list of conditions, and the following disclaimer.
#   * Redistributions in binary form must reproduce the above copyright notice,
#     this list of conditions, and the following disclaimer in the
#     documentation and/or other materials provided with the distribution.
#   * Neither the name of the author of this software nor the name of
#     contributors to this software may be used to endorse or promote products
#     derived from this software without specific prior written consent.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
###

__revision__ = '$Hg:$'

# system imports
import types

# DDB imports
from ddb.lang import lang
from ddb.log import log, logException
from ddb.event import event

# Twisted imports
from twisted.web import client, http, microdom, domhelpers

class IFeedback:
    callbacks = {}

    def _onMessage(self, event):
        type     = event.transport.type
        name     = event.transport.name
        target   = event.target.lower()
        identity = event.user.identity
        if not self.callbacks.has_key(type):
            return
        if not self.callbacks[type].has_key(name):
            return
        if not self.callbacks[type][name].has_key(target):
            return
        triggers = self.callbacks[type][name][target]
        for trigger in triggers:
            if id(event) == trigger['event']:
                # oh we're ignoring this
                continue
            elif ((event.message.lower() in trigger['answers']) or (trigger['answer'] == [])) and \
                 ((identity in trigger['identity']) or (trigger['identity'] == [])):
                event.rawevent = trigger['event']
                trigger['callback'](event, *trigger['args'], **trigger['kwargs'])
                self.callbacks[type][name][target].remove(trigger)
                return
            elif identity in trigger['identity'] and not trigger['wait']:
                if trigger['complain']:
                    trigger['event'].reply(lang('did not answer question'))
                if trigger['warn']:
                    trigger['event'].reply(lang('stop wait for feedback'))
                self.callbacks[type][name][target].remove(trigger)
            elif identity in trigger['identity']:
                if trigger['complain']:
                    trigger['event'].reply(lang('did not answer question'))

    def wait(self, event, answers, callback, identity=None, complain=False, wait=False, warn=False, *args, **kwargs):
        """Waits for an answer on the transport.

        @answers:  list of possible answers
        @callback: what do we call if we get our answer
        @identity: list or string of the identity we expect the answer from
        @complain: warn the user if he did not answer the question
        @wait:     if set to True, we'll wait until we get an answer
                   if set to False, we'll only check if the next line
                   contains one of the possible answers.
        @warn:     warn the user if we stop waiting for feedback
        """
        ttype  = event.transport.type
        name   = event.transport.name
        target = event.target.lower()
        if not identity:
            identity = event.user.identity
        if not type(identity) == types.ListType:
            identity = [identity]
        if not type(answers) == types.ListType:
            answers = [answers]
        if not self.callbacks.has_key(type):
            self.callbacks[ttype] = {}
        if not self.callbacks[ttype].has_key(name):
            self.callbacks[ttype][name] = {}
        if not self.callbacks[ttype][name].has_key(target):
            self.callbacks[ttype][name][target] = []
        self.callbacks[ttype][name][target].append({
            'answers':  [x.lower() for x in answers],
            'callback': callback,
            'identity': identity,
            'complain': complain,
            'wait':     wait,
            'warn':     warn,
            'args':     args,
            'kwargs':   kwargs,
            'event':    event
            })
        event.halt() # stop the hook chain, settle for feedback

feedback = IFeedback()

# exports
bind = (
    ['message', feedback._onMessage, 81],
    )

# vim:ts=4:sw=4:et:
